Add a drag_data_received handler for the label.
authorOwen Taylor <otaylor@redhat.com>
Tue, 12 Jan 1999 23:27:30 +0000 (23:27 +0000)
committerOwen Taylor <otaylor@src.gnome.org>
Tue, 12 Jan 1999 23:27:30 +0000 (23:27 +0000)
Tue Jan 12 18:30:51 1999  Owen Taylor  <otaylor@redhat.com>

* gtk/testdnd.c (label_drag_data_received): Add
a drag_data_received handler for the label.

Tue Jan 12 15:01:50 1999  Owen Taylor  <otaylor@redhat.com>

        * gdk/gdkevents.c: Removed the putback_events queue,
since it was causing problems with event ordering -
just keep a single queue. If we need it, we can
add priorities to events.

* gdk/gdkevents.c: Annotate events with flags - we allocate
a GdkEventPrivate structure in gdk_event_new() and use these
flags to mark an event being translated as "pending" -
I.e., not yet ready to be dequeued. So we can put
the event on the queue and get the order of the
events right. (This solves the double-click problems)

* gdk/gdk.h gdk/gdkevents.h: Add gdk_event_peek() to get a copy
of the next event on the event queue.

* gtk/gtkmain.c (gtk_main_do_event): Use gdk_event_peek()
to check the next event without causing event queue
reordering.

13 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gdk/gdk.h
gdk/gdkevents.c
gdk/x11/gdkevents-x11.c
gtk/gtkmain.c
gtk/testdnd.c
tests/testdnd.c

index f7a6ea3bffcd495e5ad9d2b3d37865754c846872..0dd7d9af51b1684b4ed4d5b2b083eec7dc30d82b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+Tue Jan 12 18:30:51 1999  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/testdnd.c (label_drag_data_received): Add 
+       a drag_data_received handler for the label.
+
+Tue Jan 12 15:01:50 1999  Owen Taylor  <otaylor@redhat.com>
+
+        * gdk/gdkevents.c: Removed the putback_events queue, 
+       since it was causing problems with event ordering -
+       just keep a single queue. If we need it, we can
+       add priorities to events.
+
+       * gdk/gdkevents.c: Annotate events with flags - we allocate
+       a GdkEventPrivate structure in gdk_event_new() and use these
+       flags to mark an event being translated as "pending" -
+       I.e., not yet ready to be dequeued. So we can put
+       the event on the queue and get the order of the
+       events right. (This solves the double-click problems)
+       
+       * gdk/gdk.h gdk/gdkevents.h: Add gdk_event_peek() to get a copy
+       of the next event on the event queue.
+       
+       * gtk/gtkmain.c (gtk_main_do_event): Use gdk_event_peek()
+       to check the next event without causing event queue
+       reordering.
+
 Tue Jan 12 15:41:20 1999  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtklabel.c (gtk_label_expose): Minor fix
index f7a6ea3bffcd495e5ad9d2b3d37865754c846872..0dd7d9af51b1684b4ed4d5b2b083eec7dc30d82b 100644 (file)
@@ -1,3 +1,29 @@
+Tue Jan 12 18:30:51 1999  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/testdnd.c (label_drag_data_received): Add 
+       a drag_data_received handler for the label.
+
+Tue Jan 12 15:01:50 1999  Owen Taylor  <otaylor@redhat.com>
+
+        * gdk/gdkevents.c: Removed the putback_events queue, 
+       since it was causing problems with event ordering -
+       just keep a single queue. If we need it, we can
+       add priorities to events.
+
+       * gdk/gdkevents.c: Annotate events with flags - we allocate
+       a GdkEventPrivate structure in gdk_event_new() and use these
+       flags to mark an event being translated as "pending" -
+       I.e., not yet ready to be dequeued. So we can put
+       the event on the queue and get the order of the
+       events right. (This solves the double-click problems)
+       
+       * gdk/gdk.h gdk/gdkevents.h: Add gdk_event_peek() to get a copy
+       of the next event on the event queue.
+       
+       * gtk/gtkmain.c (gtk_main_do_event): Use gdk_event_peek()
+       to check the next event without causing event queue
+       reordering.
+
 Tue Jan 12 15:41:20 1999  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtklabel.c (gtk_label_expose): Minor fix
index f7a6ea3bffcd495e5ad9d2b3d37865754c846872..0dd7d9af51b1684b4ed4d5b2b083eec7dc30d82b 100644 (file)
@@ -1,3 +1,29 @@
+Tue Jan 12 18:30:51 1999  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/testdnd.c (label_drag_data_received): Add 
+       a drag_data_received handler for the label.
+
+Tue Jan 12 15:01:50 1999  Owen Taylor  <otaylor@redhat.com>
+
+        * gdk/gdkevents.c: Removed the putback_events queue, 
+       since it was causing problems with event ordering -
+       just keep a single queue. If we need it, we can
+       add priorities to events.
+
+       * gdk/gdkevents.c: Annotate events with flags - we allocate
+       a GdkEventPrivate structure in gdk_event_new() and use these
+       flags to mark an event being translated as "pending" -
+       I.e., not yet ready to be dequeued. So we can put
+       the event on the queue and get the order of the
+       events right. (This solves the double-click problems)
+       
+       * gdk/gdk.h gdk/gdkevents.h: Add gdk_event_peek() to get a copy
+       of the next event on the event queue.
+       
+       * gtk/gtkmain.c (gtk_main_do_event): Use gdk_event_peek()
+       to check the next event without causing event queue
+       reordering.
+
 Tue Jan 12 15:41:20 1999  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtklabel.c (gtk_label_expose): Minor fix
index f7a6ea3bffcd495e5ad9d2b3d37865754c846872..0dd7d9af51b1684b4ed4d5b2b083eec7dc30d82b 100644 (file)
@@ -1,3 +1,29 @@
+Tue Jan 12 18:30:51 1999  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/testdnd.c (label_drag_data_received): Add 
+       a drag_data_received handler for the label.
+
+Tue Jan 12 15:01:50 1999  Owen Taylor  <otaylor@redhat.com>
+
+        * gdk/gdkevents.c: Removed the putback_events queue, 
+       since it was causing problems with event ordering -
+       just keep a single queue. If we need it, we can
+       add priorities to events.
+
+       * gdk/gdkevents.c: Annotate events with flags - we allocate
+       a GdkEventPrivate structure in gdk_event_new() and use these
+       flags to mark an event being translated as "pending" -
+       I.e., not yet ready to be dequeued. So we can put
+       the event on the queue and get the order of the
+       events right. (This solves the double-click problems)
+       
+       * gdk/gdk.h gdk/gdkevents.h: Add gdk_event_peek() to get a copy
+       of the next event on the event queue.
+       
+       * gtk/gtkmain.c (gtk_main_do_event): Use gdk_event_peek()
+       to check the next event without causing event queue
+       reordering.
+
 Tue Jan 12 15:41:20 1999  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtklabel.c (gtk_label_expose): Minor fix
index f7a6ea3bffcd495e5ad9d2b3d37865754c846872..0dd7d9af51b1684b4ed4d5b2b083eec7dc30d82b 100644 (file)
@@ -1,3 +1,29 @@
+Tue Jan 12 18:30:51 1999  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/testdnd.c (label_drag_data_received): Add 
+       a drag_data_received handler for the label.
+
+Tue Jan 12 15:01:50 1999  Owen Taylor  <otaylor@redhat.com>
+
+        * gdk/gdkevents.c: Removed the putback_events queue, 
+       since it was causing problems with event ordering -
+       just keep a single queue. If we need it, we can
+       add priorities to events.
+
+       * gdk/gdkevents.c: Annotate events with flags - we allocate
+       a GdkEventPrivate structure in gdk_event_new() and use these
+       flags to mark an event being translated as "pending" -
+       I.e., not yet ready to be dequeued. So we can put
+       the event on the queue and get the order of the
+       events right. (This solves the double-click problems)
+       
+       * gdk/gdk.h gdk/gdkevents.h: Add gdk_event_peek() to get a copy
+       of the next event on the event queue.
+       
+       * gtk/gtkmain.c (gtk_main_do_event): Use gdk_event_peek()
+       to check the next event without causing event queue
+       reordering.
+
 Tue Jan 12 15:41:20 1999  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtklabel.c (gtk_label_expose): Minor fix
index f7a6ea3bffcd495e5ad9d2b3d37865754c846872..0dd7d9af51b1684b4ed4d5b2b083eec7dc30d82b 100644 (file)
@@ -1,3 +1,29 @@
+Tue Jan 12 18:30:51 1999  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/testdnd.c (label_drag_data_received): Add 
+       a drag_data_received handler for the label.
+
+Tue Jan 12 15:01:50 1999  Owen Taylor  <otaylor@redhat.com>
+
+        * gdk/gdkevents.c: Removed the putback_events queue, 
+       since it was causing problems with event ordering -
+       just keep a single queue. If we need it, we can
+       add priorities to events.
+
+       * gdk/gdkevents.c: Annotate events with flags - we allocate
+       a GdkEventPrivate structure in gdk_event_new() and use these
+       flags to mark an event being translated as "pending" -
+       I.e., not yet ready to be dequeued. So we can put
+       the event on the queue and get the order of the
+       events right. (This solves the double-click problems)
+       
+       * gdk/gdk.h gdk/gdkevents.h: Add gdk_event_peek() to get a copy
+       of the next event on the event queue.
+       
+       * gtk/gtkmain.c (gtk_main_do_event): Use gdk_event_peek()
+       to check the next event without causing event queue
+       reordering.
+
 Tue Jan 12 15:41:20 1999  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtklabel.c (gtk_label_expose): Minor fix
index f7a6ea3bffcd495e5ad9d2b3d37865754c846872..0dd7d9af51b1684b4ed4d5b2b083eec7dc30d82b 100644 (file)
@@ -1,3 +1,29 @@
+Tue Jan 12 18:30:51 1999  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/testdnd.c (label_drag_data_received): Add 
+       a drag_data_received handler for the label.
+
+Tue Jan 12 15:01:50 1999  Owen Taylor  <otaylor@redhat.com>
+
+        * gdk/gdkevents.c: Removed the putback_events queue, 
+       since it was causing problems with event ordering -
+       just keep a single queue. If we need it, we can
+       add priorities to events.
+
+       * gdk/gdkevents.c: Annotate events with flags - we allocate
+       a GdkEventPrivate structure in gdk_event_new() and use these
+       flags to mark an event being translated as "pending" -
+       I.e., not yet ready to be dequeued. So we can put
+       the event on the queue and get the order of the
+       events right. (This solves the double-click problems)
+       
+       * gdk/gdk.h gdk/gdkevents.h: Add gdk_event_peek() to get a copy
+       of the next event on the event queue.
+       
+       * gtk/gtkmain.c (gtk_main_do_event): Use gdk_event_peek()
+       to check the next event without causing event queue
+       reordering.
+
 Tue Jan 12 15:41:20 1999  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtklabel.c (gtk_label_expose): Minor fix
index 97441a27d316d59cb6678ae47799b93ea17b7f31..a35f6e57bc394349f466325f1dfb66e4dd111367 100644 (file)
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -37,6 +37,8 @@ gchar*          gdk_set_locale                (void);
 
 gboolean  gdk_events_pending           (void);
 GdkEvent* gdk_event_get                        (void);
+
+GdkEvent* gdk_event_peek                (void);
 GdkEvent* gdk_event_get_graphics_expose (GdkWindow     *window);
 void      gdk_event_put                        (GdkEvent       *event);
 
index e8b0444467c0b4ca78870517acb7c770182613f2..24e1b67a04b08122399ecd4859d8a303f8f6686d 100644 (file)
 
 
 typedef struct _GdkIOClosure GdkIOClosure;
+typedef struct _GdkEventPrivate GdkEventPrivate;
 
 #define DOUBLE_CLICK_TIME      250
 #define TRIPLE_CLICK_TIME      500
 #define DOUBLE_CLICK_DIST      5
 #define TRIPLE_CLICK_DIST      5
 
+typedef enum {
+  /* Following flag is set for events on the event queue during
+   * translation and cleared afterwards.
+   */
+  GDK_EVENT_PENDING = 1 << 0
+} GdkEventFlags;
+
 struct _GdkIOClosure {
   GdkInputFunction function;
   GdkInputCondition condition;
@@ -45,6 +53,11 @@ struct _GdkIOClosure {
   gpointer data;
 };
 
+struct _GdkEventPrivate {
+  GdkEvent event;
+  guint    flags;
+};
+
 /* 
  * Private function declarations
  */
@@ -105,14 +118,10 @@ static GDestroyNotify event_notify;
 static GList *client_filters;                      /* Filters for client messages */
 
 /* FIFO's for event queue, and for events put back using
- * gdk_event_put(). We keep separate queues so that
- * we can make the putback events both FIFO and preemptive
- * of pending events.
+ * gdk_event_put().
  */
 static GList *queued_events = NULL;
 static GList *queued_tail = NULL;
-static GList *putback_events = NULL;
-static GList *putback_tail = NULL;
 
 static GSourceFuncs event_funcs = {
   gdk_event_prepare,
@@ -123,6 +132,77 @@ static GSourceFuncs event_funcs = {
 
 GPollFD event_poll_fd;
 
+/*********************************************
+ * Functions for maintaining the event queue *
+ *********************************************/
+
+/*************************************************************
+ * gdk_event_queue_find_first:
+ *     Find the first event on the queue that is not still
+ *     being filled in.
+ *   arguments:
+ *     
+ *   results:
+ *     Pointer to the list node for that event, or NULL
+ *************************************************************/
+
+static GList *
+gdk_event_queue_find_first (void)
+{
+  GList *tmp_list = queued_events;
+
+  while (tmp_list)
+    {
+      GdkEventPrivate *event = queued_events->data;
+      if (!(event->flags & GDK_EVENT_PENDING))
+       return tmp_list;
+    }
+
+  return NULL;
+}
+
+/*************************************************************
+ * gdk_event_queue_remove_link:
+ *     Remove a specified list node from the event queue.
+ *   arguments:
+ *     node: Node to remove.
+ *   results:
+ *************************************************************/
+
+static void
+gdk_event_queue_remove_link (GList *node)
+{
+  if (node->prev)
+    node->prev->next = node->next;
+  else
+    queued_events = node->next;
+  
+  if (node->next)
+    node->next->prev = node->prev;
+  else
+    queued_tail = node->prev;
+  
+}
+
+/*************************************************************
+ * gdk_event_queue_append:
+ *     Append an event onto the tail of the event queue.
+ *   arguments:
+ *     event: Event to append.
+ *   results:
+ *************************************************************/
+
+static void
+gdk_event_queue_append (GdkEvent *event)
+{
+  queued_tail = g_list_append(queued_tail, event);
+  
+  if (!queued_events)
+    queued_events = queued_tail;
+  else
+    queued_tail = queued_tail->next;
+}
+
 void 
 gdk_events_init (void)
 {
@@ -137,10 +217,6 @@ gdk_events_init (void)
   
   g_main_add_poll (&event_poll_fd, GDK_PRIORITY_EVENTS);
 
-  /* This is really crappy. We have to look into the display structure
-   *  to find the base resource id. This is only needed for recording
-   *  and playback of events.
-   */
   button_click_time[0] = 0;
   button_click_time[1] = 0;
   button_window[0] = NULL;
@@ -171,7 +247,7 @@ gdk_events_init (void)
 gboolean
 gdk_events_pending (void)
 {
-  return (queued_events || putback_events);
+  return (gdk_event_queue_find_first() || XPending (gdk_display));
 }
 
 /*
@@ -451,11 +527,9 @@ gdk_event_handler_set (GdkEventFunc   func,
  * Arguments:
  *
  * Results:
- *   If an event was received that we care about, returns 
+ *   If an event is waiting that we care about, returns 
  *   a pointer to that event, to be freed with gdk_event_free.
- *   Otherwise, returns NULL. This function will also return
- *   before an event is received if the timeout interval
- *   runs out.
+ *   Otherwise, returns NULL.
  *
  * Side effects:
  *
@@ -470,6 +544,38 @@ gdk_event_get (void)
   return gdk_event_unqueue();
 }
 
+/*
+ *--------------------------------------------------------------
+ * gdk_event_peek
+ *
+ *   Gets the next event.
+ *
+ * Arguments:
+ *
+ * Results:
+ *   If an event is waiting that we care about, returns 
+ *   a copy of that event, but does not remove it from
+ *   the queue. The pointer is to be freed with gdk_event_free.
+ *   Otherwise, returns NULL.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+GdkEvent *
+gdk_event_peek (void)
+{
+  GList *tmp_list;
+
+  tmp_list = gdk_event_queue_find_first ();
+  
+  if (tmp_list)
+    return gdk_event_copy (tmp_list->data);
+  else
+    return NULL;
+}
+
 void
 gdk_event_put (GdkEvent *event)
 {
@@ -479,12 +585,7 @@ gdk_event_put (GdkEvent *event)
   
   new_event = gdk_event_copy (event);
 
-  putback_tail = g_list_append(putback_tail, new_event);
-
-  if (!putback_events)
-    putback_events = putback_tail;
-  else
-    putback_tail = putback_tail->next;
+  gdk_event_queue_append (new_event);
 }
 
 /*
@@ -510,17 +611,18 @@ static GMemChunk *event_chunk;
 static GdkEvent*
 gdk_event_new (void)
 {
-  GdkEvent *new_event;
+  GdkEventPrivate *new_event;
   
   if (event_chunk == NULL)
     event_chunk = g_mem_chunk_new ("events",
-                                  sizeof (GdkEvent),
+                                  sizeof (GdkEventPrivate),
                                   4096,
                                   G_ALLOC_AND_FREE);
   
-  new_event = g_chunk_new (GdkEvent, event_chunk);
+  new_event = g_chunk_new (GdkEventPrivate, event_chunk);
+  new_event->flags = 0;
   
-  return new_event;
+  return (GdkEvent *)new_event;
 }
 
 GdkEvent*
@@ -1835,10 +1937,11 @@ gdk_event_get_type (Display  *display,
 static void
 gdk_events_queue (void)
 {
+  GList *node;
   GdkEvent *event;
   XEvent xevent;
 
-  while (!(putback_events || queued_events) && XPending (gdk_display))
+  while (!gdk_event_queue_find_first() && XPending (gdk_display))
     {
   #ifdef USE_XIM
       Window w = None;
@@ -1867,18 +1970,22 @@ gdk_events_queue (void)
       event->any.window = NULL;
       event->any.send_event = FALSE;
       event->any.send_event = xevent.xany.send_event;
-      
+
+      ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
+
+      gdk_event_queue_append (event);
+      node = queued_tail;
+
       if (gdk_event_translate (event, &xevent))
        {
-         queued_tail = g_list_append(queued_tail, event);
-
-         if (!queued_events)
-           queued_events = queued_tail;
-         else
-           queued_tail = queued_tail->next;
+         ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
        }
       else
-       gdk_event_free (event);
+       {
+         gdk_event_queue_remove_link (node);
+         g_list_free_1 (node);
+         gdk_event_free (event);
+       }
     }
 }
 
@@ -1894,7 +2001,7 @@ gdk_event_prepare (gpointer  source_data,
   *timeout = -1;
 
   gdk_events_queue ();
-  retval = (queued_events || putback_events);
+  retval = (gdk_event_queue_find_first () != NULL);
 
   GDK_THREADS_LEAVE ();
 
@@ -1912,7 +2019,7 @@ gdk_event_check   (gpointer  source_data,
   if (event_poll_fd.revents & G_IO_IN)
       gdk_events_queue ();
 
-  retval = (queued_events || putback_events);
+  retval = (gdk_event_queue_find_first () != NULL);
 
   GDK_THREADS_LEAVE ();
 
@@ -1922,29 +2029,17 @@ gdk_event_check   (gpointer  source_data,
 static GdkEvent *
 gdk_event_unqueue (void)
 {
-  GdkEvent *event;
-  GList *tmp_list, **head, **tail;
+  GdkEvent *event = NULL;
+  GList *tmp_list;
 
-  if (putback_events)
-    {
-      head = &putback_events;
-      tail = &putback_tail;
-    }
-  else if (queued_events)
+  tmp_list = gdk_event_queue_find_first ();
+
+  if (tmp_list)
     {
-      head = &queued_events;
-      tail = &queued_tail;
+      event = tmp_list->data;
+      gdk_event_queue_remove_link (tmp_list);
+      g_list_free_1 (tmp_list);
     }
-  else
-    return NULL;
-
-  if (*head == *tail)
-    *tail = NULL;
-    
-  tmp_list = *head;
-  event = tmp_list->data;
-  *head = g_list_remove_link (tmp_list, tmp_list);
-  g_list_free_1 (tmp_list);
 
   return event;
 }
index e8b0444467c0b4ca78870517acb7c770182613f2..24e1b67a04b08122399ecd4859d8a303f8f6686d 100644 (file)
 
 
 typedef struct _GdkIOClosure GdkIOClosure;
+typedef struct _GdkEventPrivate GdkEventPrivate;
 
 #define DOUBLE_CLICK_TIME      250
 #define TRIPLE_CLICK_TIME      500
 #define DOUBLE_CLICK_DIST      5
 #define TRIPLE_CLICK_DIST      5
 
+typedef enum {
+  /* Following flag is set for events on the event queue during
+   * translation and cleared afterwards.
+   */
+  GDK_EVENT_PENDING = 1 << 0
+} GdkEventFlags;
+
 struct _GdkIOClosure {
   GdkInputFunction function;
   GdkInputCondition condition;
@@ -45,6 +53,11 @@ struct _GdkIOClosure {
   gpointer data;
 };
 
+struct _GdkEventPrivate {
+  GdkEvent event;
+  guint    flags;
+};
+
 /* 
  * Private function declarations
  */
@@ -105,14 +118,10 @@ static GDestroyNotify event_notify;
 static GList *client_filters;                      /* Filters for client messages */
 
 /* FIFO's for event queue, and for events put back using
- * gdk_event_put(). We keep separate queues so that
- * we can make the putback events both FIFO and preemptive
- * of pending events.
+ * gdk_event_put().
  */
 static GList *queued_events = NULL;
 static GList *queued_tail = NULL;
-static GList *putback_events = NULL;
-static GList *putback_tail = NULL;
 
 static GSourceFuncs event_funcs = {
   gdk_event_prepare,
@@ -123,6 +132,77 @@ static GSourceFuncs event_funcs = {
 
 GPollFD event_poll_fd;
 
+/*********************************************
+ * Functions for maintaining the event queue *
+ *********************************************/
+
+/*************************************************************
+ * gdk_event_queue_find_first:
+ *     Find the first event on the queue that is not still
+ *     being filled in.
+ *   arguments:
+ *     
+ *   results:
+ *     Pointer to the list node for that event, or NULL
+ *************************************************************/
+
+static GList *
+gdk_event_queue_find_first (void)
+{
+  GList *tmp_list = queued_events;
+
+  while (tmp_list)
+    {
+      GdkEventPrivate *event = queued_events->data;
+      if (!(event->flags & GDK_EVENT_PENDING))
+       return tmp_list;
+    }
+
+  return NULL;
+}
+
+/*************************************************************
+ * gdk_event_queue_remove_link:
+ *     Remove a specified list node from the event queue.
+ *   arguments:
+ *     node: Node to remove.
+ *   results:
+ *************************************************************/
+
+static void
+gdk_event_queue_remove_link (GList *node)
+{
+  if (node->prev)
+    node->prev->next = node->next;
+  else
+    queued_events = node->next;
+  
+  if (node->next)
+    node->next->prev = node->prev;
+  else
+    queued_tail = node->prev;
+  
+}
+
+/*************************************************************
+ * gdk_event_queue_append:
+ *     Append an event onto the tail of the event queue.
+ *   arguments:
+ *     event: Event to append.
+ *   results:
+ *************************************************************/
+
+static void
+gdk_event_queue_append (GdkEvent *event)
+{
+  queued_tail = g_list_append(queued_tail, event);
+  
+  if (!queued_events)
+    queued_events = queued_tail;
+  else
+    queued_tail = queued_tail->next;
+}
+
 void 
 gdk_events_init (void)
 {
@@ -137,10 +217,6 @@ gdk_events_init (void)
   
   g_main_add_poll (&event_poll_fd, GDK_PRIORITY_EVENTS);
 
-  /* This is really crappy. We have to look into the display structure
-   *  to find the base resource id. This is only needed for recording
-   *  and playback of events.
-   */
   button_click_time[0] = 0;
   button_click_time[1] = 0;
   button_window[0] = NULL;
@@ -171,7 +247,7 @@ gdk_events_init (void)
 gboolean
 gdk_events_pending (void)
 {
-  return (queued_events || putback_events);
+  return (gdk_event_queue_find_first() || XPending (gdk_display));
 }
 
 /*
@@ -451,11 +527,9 @@ gdk_event_handler_set (GdkEventFunc   func,
  * Arguments:
  *
  * Results:
- *   If an event was received that we care about, returns 
+ *   If an event is waiting that we care about, returns 
  *   a pointer to that event, to be freed with gdk_event_free.
- *   Otherwise, returns NULL. This function will also return
- *   before an event is received if the timeout interval
- *   runs out.
+ *   Otherwise, returns NULL.
  *
  * Side effects:
  *
@@ -470,6 +544,38 @@ gdk_event_get (void)
   return gdk_event_unqueue();
 }
 
+/*
+ *--------------------------------------------------------------
+ * gdk_event_peek
+ *
+ *   Gets the next event.
+ *
+ * Arguments:
+ *
+ * Results:
+ *   If an event is waiting that we care about, returns 
+ *   a copy of that event, but does not remove it from
+ *   the queue. The pointer is to be freed with gdk_event_free.
+ *   Otherwise, returns NULL.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+GdkEvent *
+gdk_event_peek (void)
+{
+  GList *tmp_list;
+
+  tmp_list = gdk_event_queue_find_first ();
+  
+  if (tmp_list)
+    return gdk_event_copy (tmp_list->data);
+  else
+    return NULL;
+}
+
 void
 gdk_event_put (GdkEvent *event)
 {
@@ -479,12 +585,7 @@ gdk_event_put (GdkEvent *event)
   
   new_event = gdk_event_copy (event);
 
-  putback_tail = g_list_append(putback_tail, new_event);
-
-  if (!putback_events)
-    putback_events = putback_tail;
-  else
-    putback_tail = putback_tail->next;
+  gdk_event_queue_append (new_event);
 }
 
 /*
@@ -510,17 +611,18 @@ static GMemChunk *event_chunk;
 static GdkEvent*
 gdk_event_new (void)
 {
-  GdkEvent *new_event;
+  GdkEventPrivate *new_event;
   
   if (event_chunk == NULL)
     event_chunk = g_mem_chunk_new ("events",
-                                  sizeof (GdkEvent),
+                                  sizeof (GdkEventPrivate),
                                   4096,
                                   G_ALLOC_AND_FREE);
   
-  new_event = g_chunk_new (GdkEvent, event_chunk);
+  new_event = g_chunk_new (GdkEventPrivate, event_chunk);
+  new_event->flags = 0;
   
-  return new_event;
+  return (GdkEvent *)new_event;
 }
 
 GdkEvent*
@@ -1835,10 +1937,11 @@ gdk_event_get_type (Display  *display,
 static void
 gdk_events_queue (void)
 {
+  GList *node;
   GdkEvent *event;
   XEvent xevent;
 
-  while (!(putback_events || queued_events) && XPending (gdk_display))
+  while (!gdk_event_queue_find_first() && XPending (gdk_display))
     {
   #ifdef USE_XIM
       Window w = None;
@@ -1867,18 +1970,22 @@ gdk_events_queue (void)
       event->any.window = NULL;
       event->any.send_event = FALSE;
       event->any.send_event = xevent.xany.send_event;
-      
+
+      ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
+
+      gdk_event_queue_append (event);
+      node = queued_tail;
+
       if (gdk_event_translate (event, &xevent))
        {
-         queued_tail = g_list_append(queued_tail, event);
-
-         if (!queued_events)
-           queued_events = queued_tail;
-         else
-           queued_tail = queued_tail->next;
+         ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
        }
       else
-       gdk_event_free (event);
+       {
+         gdk_event_queue_remove_link (node);
+         g_list_free_1 (node);
+         gdk_event_free (event);
+       }
     }
 }
 
@@ -1894,7 +2001,7 @@ gdk_event_prepare (gpointer  source_data,
   *timeout = -1;
 
   gdk_events_queue ();
-  retval = (queued_events || putback_events);
+  retval = (gdk_event_queue_find_first () != NULL);
 
   GDK_THREADS_LEAVE ();
 
@@ -1912,7 +2019,7 @@ gdk_event_check   (gpointer  source_data,
   if (event_poll_fd.revents & G_IO_IN)
       gdk_events_queue ();
 
-  retval = (queued_events || putback_events);
+  retval = (gdk_event_queue_find_first () != NULL);
 
   GDK_THREADS_LEAVE ();
 
@@ -1922,29 +2029,17 @@ gdk_event_check   (gpointer  source_data,
 static GdkEvent *
 gdk_event_unqueue (void)
 {
-  GdkEvent *event;
-  GList *tmp_list, **head, **tail;
+  GdkEvent *event = NULL;
+  GList *tmp_list;
 
-  if (putback_events)
-    {
-      head = &putback_events;
-      tail = &putback_tail;
-    }
-  else if (queued_events)
+  tmp_list = gdk_event_queue_find_first ();
+
+  if (tmp_list)
     {
-      head = &queued_events;
-      tail = &queued_tail;
+      event = tmp_list->data;
+      gdk_event_queue_remove_link (tmp_list);
+      g_list_free_1 (tmp_list);
     }
-  else
-    return NULL;
-
-  if (*head == *tail)
-    *tail = NULL;
-    
-  tmp_list = *head;
-  event = tmp_list->data;
-  *head = g_list_remove_link (tmp_list, tmp_list);
-  g_list_free_1 (tmp_list);
 
   return event;
 }
index 57f78d51728474564795233dba66da860f7013e4..4e04df9382b1d952abf2ed42a0df0a7812a5f64a 100644 (file)
@@ -553,7 +553,7 @@ gtk_main_do_event (GdkEvent *event)
 
   /* If there are any events pending then get the next one.
    */
-  next_event = gdk_event_get ();
+  next_event = gdk_event_peek ();
   
   /* Try to compress enter/leave notify events. These event
    *  pairs occur when the mouse is dragged quickly across
@@ -571,19 +571,17 @@ gtk_main_do_event (GdkEvent *event)
        (next_event->type != event->type) &&
        (next_event->any.window == event->any.window))
       {
+       /* Throw both the peeked copy and the queued copy away 
+        */
+       gdk_event_free (next_event);
+       next_event = gdk_event_get ();
        gdk_event_free (next_event);
-       next_event = NULL;
        
        return;
       }
-  
 
   if (next_event)
-    {
-      gdk_event_put (next_event);
-      gdk_event_free (next_event);
-      next_event = NULL;
-    }
+    gdk_event_free (next_event);
 
   /* Find the widget which got the event. We store the widget
    *  in the user_data field of GdkWindow's.
index 118e04d427177fc4c608a93fba0b4b511850c7ed..263e7f50dc6e7d86846b1304830e97bb4dfb6c09 100644 (file)
@@ -350,7 +350,7 @@ target_drag_data_received  (GtkWidget          *widget,
 {
   if ((data->length >= 0) && (data->format == 8))
     {
-      g_print ("Received %s\n", (gchar *)data->data);
+      g_print ("Received \"%s\" in trashcan\n", (gchar *)data->data);
       gtk_drag_finish (context, TRUE, FALSE, time);
       return;
     }
@@ -358,6 +358,25 @@ target_drag_data_received  (GtkWidget          *widget,
   gtk_drag_finish (context, FALSE, FALSE, time);
 }
   
+void  
+label_drag_data_received  (GtkWidget          *widget,
+                           GdkDragContext     *context,
+                           gint                x,
+                           gint                y,
+                           GtkSelectionData   *data,
+                           guint               info,
+                           guint               time)
+{
+  if ((data->length >= 0) && (data->format == 8))
+    {
+      g_print ("Received \"%s\" in label\n", (gchar *)data->data);
+      gtk_drag_finish (context, TRUE, FALSE, time);
+      return;
+    }
+  
+  gtk_drag_finish (context, FALSE, FALSE, time);
+}
+
 void  
 source_drag_data_get  (GtkWidget          *widget,
                       GdkDragContext     *context,
@@ -560,6 +579,9 @@ main (int argc, char **argv)
                     target_table, n_targets - 1, /* no rootwin */
                     GDK_ACTION_COPY | GDK_ACTION_MOVE);
 
+  gtk_signal_connect( GTK_OBJECT(label), "drag_data_received",
+                     GTK_SIGNAL_FUNC( label_drag_data_received), NULL);
+
   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
                    GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
                    0, 0);
index 118e04d427177fc4c608a93fba0b4b511850c7ed..263e7f50dc6e7d86846b1304830e97bb4dfb6c09 100644 (file)
@@ -350,7 +350,7 @@ target_drag_data_received  (GtkWidget          *widget,
 {
   if ((data->length >= 0) && (data->format == 8))
     {
-      g_print ("Received %s\n", (gchar *)data->data);
+      g_print ("Received \"%s\" in trashcan\n", (gchar *)data->data);
       gtk_drag_finish (context, TRUE, FALSE, time);
       return;
     }
@@ -358,6 +358,25 @@ target_drag_data_received  (GtkWidget          *widget,
   gtk_drag_finish (context, FALSE, FALSE, time);
 }
   
+void  
+label_drag_data_received  (GtkWidget          *widget,
+                           GdkDragContext     *context,
+                           gint                x,
+                           gint                y,
+                           GtkSelectionData   *data,
+                           guint               info,
+                           guint               time)
+{
+  if ((data->length >= 0) && (data->format == 8))
+    {
+      g_print ("Received \"%s\" in label\n", (gchar *)data->data);
+      gtk_drag_finish (context, TRUE, FALSE, time);
+      return;
+    }
+  
+  gtk_drag_finish (context, FALSE, FALSE, time);
+}
+
 void  
 source_drag_data_get  (GtkWidget          *widget,
                       GdkDragContext     *context,
@@ -560,6 +579,9 @@ main (int argc, char **argv)
                     target_table, n_targets - 1, /* no rootwin */
                     GDK_ACTION_COPY | GDK_ACTION_MOVE);
 
+  gtk_signal_connect( GTK_OBJECT(label), "drag_data_received",
+                     GTK_SIGNAL_FUNC( label_drag_data_received), NULL);
+
   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
                    GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
                    0, 0);